package com.study.factory;

/**
 * 工厂模式 : 对象生产的过程交给工厂来控制,我们需要什么找工厂要就行
 * 为什么会诞生设计模式？
 * 因为代码在不断迭代的过程中,我们能知道那些是一直保持固定的东西，那些是一直变化的东西,我们根据这些进行抽取 让代码更优雅方便以后的编写跟维护
 * 总结前人的经验而来的
 */
public class FactoryMethod {

    public static void main(String[] args) {

//        Application application = new Application();
        Application application = new ConcreateProductA();
//        Product object = application.getObject("0");
        Product object = application.getObject();
        object.method1();

    }

}

//简单工厂模式 里面包含所有工厂能生产的对象的实例化细节,然后所有要拿到这些对象的直接从该工厂中拿就行
class SimpleFactory{
    public static Product createProduct(String type){
        if (type.equals("0")){
            return new ProductA();
        }else if(type.equals("1")){
            return new ProductB();
        }else{
            return null;
        }
    }
}

//以下是抽象工厂模式

interface Product{
    public void method1();
}

//比如以后可能还会有 B C D产品.... 因此我们可以做一个抽取接口Product
class ProductA implements Product{

    @Override
    public void method1(){
        System.out.println(" ProductA method1 executed. ");
    }

}

class ProductB implements Product{

    @Override
    public void method1(){
        System.out.println(" ProductB method1 executed. ");
    }
}


abstract class Application {

    //这个方法要返回一个Product出去这个行为是固定的 但是具体要返回什么Product出去 是A还是B还是C？ 这个就是不能确定的 所以我们可以进行一个改造
    //把公共的保留 可变的抽离出去让以后具体的实现去实现这个可变的部分  我们把当前类变成抽象类 该方法也改成抽象方法
    abstract Product createProduct();

    //简单工厂模式的createProduct实现如下
//    {
//
//        //... 业务代码
//
//        //但是这个new的过程 我们也得解决掉 既然要用工厂 肯定就是所有具体的new的细节都给工厂来做  (简单工厂模式)
//        return SimpleFactory.createProduct(type);
//    }

    public Product getObject(){
        Product product = createProduct();

        //...业务代码

        return product;
    }

}

//具体实现抽象类 来实现自己的个性化操作 这样有什么好处？
//1.可以满足开闭原则 以后有新的需求时直接自己新增一个来拓展 而不用修改到以前的代码 可以减少很大降低成本,降低犯错成本
//2.可以满足单一原则 就自己的类只处理自己的事情 不会夹杂很多其他别的类的东西
//3.可以使类的实例化延迟到子类
class ConcreateProductA extends Application{

    @Override
    Product createProduct() {
        //ProductA自己的个性化操作
        return new ProductA();
    }
}

class ConcreateProductB extends Application{

    @Override
    Product createProduct() {
        //ProductB自己的个性化操作
        return new ProductB();
    }
}
